package com.mustafaiev.tair.cts.facade;

import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;
import org.dozer.Mapper;
import org.springframework.security.crypto.password.StandardPasswordEncoder;

import com.mustafaiev.tair.cts.dao.IPayerDAO;
import com.mustafaiev.tair.cts.dto.PayerDTO;
import com.mustafaiev.tair.cts.exeption.DataNotRemovedException;
import com.mustafaiev.tair.cts.exeption.DataNotRetrievedException;
import com.mustafaiev.tair.cts.exeption.DataNotStoredException;
import com.mustafaiev.tair.cts.model.Payer;

public class PayerFacade implements IPayerFacade {

	private final IPayerDAO payerDao;

	private final Mapper mapper;

	private static final Logger LOGGER = Logger.getLogger(PayerFacade.class);

	public PayerFacade(final IPayerDAO payerDAO, final Mapper mapper) {
		this.payerDao = payerDAO;
		this.mapper = mapper;
	}

	@Override
	public void savePayer(final PayerDTO payerDto)
			throws DataNotStoredException {
		final Payer payer = this.mapper.map(payerDto, Payer.class);
		try {
			final StandardPasswordEncoder encoder = new StandardPasswordEncoder();
			final String encodedPassword = encoder.encode(payerDto
					.getPassword());
			payer.setPassword(encodedPassword);
			this.payerDao.doSave(payer);
		} catch (final DataNotStoredException e) {
			LOGGER.error(e.getLocalizedMessage(), e);
			throw new DataNotStoredException(e.getLocalizedMessage());
		}
	}

	@Override
	public void updatePayer(final PayerDTO payerDto)
			throws DataNotStoredException {
		final Payer payer = this.mapper.map(payerDto, Payer.class);
		try {
			payer.setId(payerDto.getId());
			this.payerDao.doUpdate(payer);
		} catch (final DataNotStoredException e) {
			LOGGER.error(e.getLocalizedMessage(), e);
			throw new DataNotStoredException(e.getLocalizedMessage());
		}

	}

	@Override
	public List<PayerDTO> retrievePayers() throws DataNotRetrievedException {

		final List<Payer> payers = this.payerDao.retrieveActivePayers();

		final List<PayerDTO> payersList = new ArrayList<PayerDTO>();
		if (payers != null) {
			for (final Payer payer : payers) {
				final PayerDTO payerDto = this.mapper
						.map(payer, PayerDTO.class);
				payerDto.setId(payer.getId());
				payersList.add(payerDto);
			}
		}
		return payersList;
	}

	@Override
	public List<PayerDTO> retrievePayersForGroup(final Long goupKey)
			throws DataNotRetrievedException {

		final List<Payer> payers = this.payerDao
				.retrieveActivePayersForGroup(goupKey);
		final List<PayerDTO> payersList = new ArrayList<PayerDTO>();
		if (payers != null) {
			for (final Payer payer : payers) {
				final PayerDTO payerDto = this.mapper
						.map(payer, PayerDTO.class);
				payerDto.setId(payer.getId());
				payersList.add(payerDto);
			}
		}
		return payersList;
	}

	@Override
	public PayerDTO retrievePayer(final Long payerId)
			throws DataNotRetrievedException {
		final Payer payer = this.payerDao.retrievePayer(payerId);
		final PayerDTO dto = this.mapper.map(payer, PayerDTO.class);
		dto.setId(payer.getId());
		return dto;
	}

	@Override
	public PayerDTO findPayer(final String payerId)
			throws DataNotRetrievedException {
		final Payer payer = this.payerDao.findByEmail(payerId);
		PayerDTO dto = null;
		if (payer != null) {
			dto = this.mapper.map(payer, PayerDTO.class);
			dto.setId(payer.getId());
		}
		return dto;
	}

	@Override
	public void deletePayers(final List<PayerDTO> payersToDelete)
			throws DataNotRemovedException {
		final List<Payer> payers = convertList(payersToDelete);
		try {
			this.payerDao.deleteBatch(payers);
		} catch (final DataNotRemovedException e) {
			LOGGER.error(e.getLocalizedMessage(), e);
		}
	}

	@Override
	public PayerDTO retrieveActiveByEmail(final String email)
			throws DataNotRetrievedException {
		final Payer payer = this.payerDao.findActiveByEmail(email.trim());
		PayerDTO dto = null;
		if (payer != null) {
			dto = this.mapper.map(payer, PayerDTO.class);
			dto.setId(payer.getId());
		}
		return dto;
	}

	private List<Payer> convertList(final List<PayerDTO> list) {
		final List<Payer> payers = new ArrayList<Payer>();
		for (final PayerDTO payerDto : list) {
			final Payer payer = this.mapper.map(payerDto, Payer.class);
			payers.add(payer);
		}
		return payers;
	}

}
